﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using HalconDotNet;

namespace Kimd.Vision
{
    [Serializable]
    public class Rectangle1NB : ShapeNB, ICloneable
    {
        public PointF StartPoint;
        public PointF EndPoint;
        public Rectangle1NB()
            : base()
        {
            TypeName = ShapeType.Rectangle1;
        }
        public override void Draw(HWindow window, Graphics g, Func<PointF, PointF> pixel2Window, Func<float, float> lenConvert, bool disableEdit)
        {
            if (disableEdit || IsShowOnly)
            {
                window.SetColor(PaintColor);
                window.SetLineWidth(LineWidth);
                if (IsFill)
                    window.SetDraw("fill");
                else
                    window.SetDraw("margin");
                window.DispRectangle1(new HTuple(StartPoint.Y), new HTuple(StartPoint.X), new HTuple(EndPoint.Y), new HTuple(EndPoint.X));
            }
            else
            {
                if (!IsSelected)
                {
                    window.SetColor(PaintColor);
                    window.SetLineWidth(LineWidth);
                    if (IsFill)
                        window.SetDraw("fill");
                    else
                        window.SetDraw("margin");
                    window.DispRectangle1(new HTuple(StartPoint.Y), new HTuple(StartPoint.X), new HTuple(EndPoint.Y), new HTuple(EndPoint.X));
                    window.SetLineWidth(1);
                    window.SetColor("yellow");
                    float len = lenConvert(5);
                    window.DispRectangle2(new HTuple(StartPoint.Y), new HTuple(StartPoint.X), 0, len, len);
                    window.DispRectangle2(new HTuple(EndPoint.Y), new HTuple(EndPoint.X), 0, len, len);
                    window.DispRectangle2(new HTuple(StartPoint.Y), new HTuple(EndPoint.X), 0, len, len);
                    window.DispRectangle2(new HTuple(EndPoint.Y), new HTuple(StartPoint.X), 0, len, len);
                    window.DispRectangle2(new HTuple((StartPoint.Y + EndPoint.Y) / 2), new HTuple((StartPoint.X + EndPoint.X) / 2), 0, len, len);
                    window.DispRectangle2(new HTuple(StartPoint.Y), new HTuple((StartPoint.X + EndPoint.X) / 2), 0, len, len);
                    window.DispRectangle2(new HTuple((StartPoint.Y + EndPoint.Y) / 2), new HTuple(StartPoint.X), 0, len, len);
                    window.DispRectangle2(new HTuple((StartPoint.Y + EndPoint.Y) / 2), new HTuple(EndPoint.X), 0, len, len);
                    window.DispRectangle2(new HTuple(EndPoint.Y), new HTuple((StartPoint.X + EndPoint.X) / 2), 0, len, len);
                }
                else
                {
                    window.SetColor("orange");
                    window.SetLineWidth(1);
                    if (IsFill)
                        window.SetDraw("fill");
                    else
                        window.SetDraw("margin");
                    window.DispRectangle1(new HTuple(StartPoint.Y), new HTuple(StartPoint.X), new HTuple(EndPoint.Y), new HTuple(EndPoint.X));
                    window.SetColor("red");
                    float len = lenConvert(5);
                    window.DispRectangle2(new HTuple(StartPoint.Y), new HTuple(StartPoint.X), 0, len, len);
                    window.DispRectangle2(new HTuple(EndPoint.Y), new HTuple(EndPoint.X), 0, len, len);
                    window.DispRectangle2(new HTuple(StartPoint.Y), new HTuple(EndPoint.X), 0, len, len);
                    window.DispRectangle2(new HTuple(EndPoint.Y), new HTuple(StartPoint.X), 0, len, len);
                    window.DispRectangle2(new HTuple((StartPoint.Y + EndPoint.Y) / 2), new HTuple((StartPoint.X + EndPoint.X) / 2), 0, len, len);
                    window.DispRectangle2(new HTuple(StartPoint.Y), new HTuple((StartPoint.X + EndPoint.X) / 2), 0, len, len);
                    window.DispRectangle2(new HTuple((StartPoint.Y + EndPoint.Y) / 2), new HTuple(StartPoint.X), 0, len, len);
                    window.DispRectangle2(new HTuple((StartPoint.Y + EndPoint.Y) / 2), new HTuple(EndPoint.X), 0, len, len);
                    window.DispRectangle2(new HTuple(EndPoint.Y), new HTuple((StartPoint.X + EndPoint.X) / 2), 0, len, len);
                }
            }
        }
        public override PositionNB PointOnShape(PointF testPoint, Func<float, float> lenConvert)
        {
            PointF center = new PointF((StartPoint.X + EndPoint.X) / 2, (StartPoint.Y + EndPoint.Y) / 2);

            distance2Handle = (int)lenConvert(10);

            double dcenter = HMisc.DistancePp(new HTuple(testPoint.Y), new HTuple(testPoint.X), new HTuple(center.Y), new HTuple(center.X));
            if (dcenter < distance2Handle)
                return PositionNB.In;
            double dleftup = HMisc.DistancePp(new HTuple(testPoint.Y), new HTuple(testPoint.X), new HTuple(StartPoint.Y), new HTuple(StartPoint.X));
            if (dleftup < distance2Handle)
                return PositionNB.LeftUp;
            double dup = HMisc.DistancePp(new HTuple(testPoint.Y), new HTuple(testPoint.X), new HTuple(StartPoint.Y), new HTuple((StartPoint.X + EndPoint.X) / 2));
            if (dup < distance2Handle)
                return PositionNB.Up;
            double drightup = HMisc.DistancePp(new HTuple(testPoint.Y), new HTuple(testPoint.X), new HTuple(StartPoint.Y), new HTuple(EndPoint.X));
            if (drightup < distance2Handle)
                return PositionNB.RightUp;
            double ddown = HMisc.DistancePp(new HTuple(testPoint.Y), new HTuple(testPoint.X), new HTuple(EndPoint.Y), new HTuple((StartPoint.X + EndPoint.X) / 2));
            if (ddown < distance2Handle)
                return PositionNB.Down;
            double dleft = HMisc.DistancePp(new HTuple(testPoint.Y), new HTuple(testPoint.X), new HTuple((StartPoint.Y + EndPoint.Y) / 2), new HTuple(StartPoint.X));
            if (dleft < distance2Handle)
                return PositionNB.Left;
            double dright = HMisc.DistancePp(new HTuple(testPoint.Y), new HTuple(testPoint.X), new HTuple((StartPoint.Y + EndPoint.Y) / 2), new HTuple(EndPoint.X));
            if (dright < distance2Handle)
                return PositionNB.Right;
            double dleftdown = HMisc.DistancePp(new HTuple(testPoint.Y), new HTuple(testPoint.X), new HTuple(EndPoint.Y), new HTuple(StartPoint.X));
            if (dleftdown < distance2Handle)
                return PositionNB.LeftDown;
            double drightdown = HMisc.DistancePp(new HTuple(testPoint.Y), new HTuple(testPoint.X), new HTuple(EndPoint.Y), new HTuple(EndPoint.X));
            if (drightdown < distance2Handle)
                return PositionNB.RightDown;
            return PositionNB.Out;
        }
        public override void Change(PointF point)
        {
            switch (ChangeModel)
            {
                case PositionNB.In:
                    PointF center = new PointF((StartPoint.X + EndPoint.X) / 2, (StartPoint.Y + EndPoint.Y) / 2);
                    float dx = point.X - center.X;
                    float dy = point.Y - center.Y;
                    this.StartPoint = new PointF(StartPoint.X + dx, StartPoint.Y + dy);
                    this.EndPoint = new PointF(EndPoint.X + dx, EndPoint.Y + dy);
                    break;
                case PositionNB.Left:
                    if (point.X < this.EndPoint.X)
                        this.StartPoint = new PointF(point.X, this.StartPoint.Y);
                    break;
                case PositionNB.Right:
                    if (point.X > this.StartPoint.X)
                        this.EndPoint = new PointF(point.X, this.EndPoint.Y);
                    break;
                case PositionNB.Up:
                    if (point.Y < this.EndPoint.Y)
                        this.StartPoint = new PointF(this.StartPoint.X, point.Y);
                    break;
                case PositionNB.Down:
                    if (point.Y > this.StartPoint.Y)
                        this.EndPoint = new PointF(this.EndPoint.X, point.Y);
                    break;
                case PositionNB.LeftUp:
                    if (point.X < this.EndPoint.X && point.Y < this.EndPoint.Y)
                        this.StartPoint = point;
                    break;
                case PositionNB.Create:
                case PositionNB.RightDown:
                    if (point.X > this.StartPoint.X && point.Y > this.StartPoint.Y)
                        this.EndPoint = point;
                    break;
                case PositionNB.LeftDown:
                    if (point.X < this.EndPoint.X && point.Y > this.StartPoint.Y)
                    {
                        this.StartPoint = new PointF(point.X, this.StartPoint.Y);
                        this.EndPoint = new PointF(this.EndPoint.X, point.Y);
                    }
                    break;
                case PositionNB.RightUp:
                    if (point.X > this.StartPoint.X && point.Y < this.EndPoint.Y)
                    {
                        this.StartPoint = new PointF(this.StartPoint.X, point.Y);
                        this.EndPoint = new PointF(point.X, this.EndPoint.Y);
                    }
                    break;
            }
        }
        public override HObject ToRegion()
        {
            HRegion reg = new HRegion();
            reg.GenRectangle1((double)StartPoint.Y, (double)StartPoint.X, (double)EndPoint.Y, (double)EndPoint.X);
            return reg;
        }
        public override void FromXmlNode(XmlNode node)
        {
            RegOperator = (ShapeOperator)Enum.Parse(typeof(ShapeOperator), node.Attributes["Operator"].Value);
            PaintColor = node.Attributes["Color"].Value;
            LineWidth = Int32.Parse(node.Attributes["LineWidth"].Value);

            foreach (XmlNode xn in node.ChildNodes)
            {
                if (xn.Name == "StartPoint")
                {
                    StartPoint = new PointF(float.Parse(xn.InnerText.Split(',')[0]),
                                            float.Parse(xn.InnerText.Split(',')[1]));
                }
                else if (xn.Name == "EndPoint")
                {
                    EndPoint = new PointF(float.Parse(xn.InnerText.Split(',')[0]),
                                            float.Parse(xn.InnerText.Split(',')[1]));
                }
                else if (xn.Name == "Alias")
                {
                    Alias = xn.InnerText;
                }
            }
        }
        public override void ToXmlNode(out Dictionary<string, object> attributes, out Dictionary<string, object> nodes)
        {
            attributes = new Dictionary<string, object>();
            attributes.Add("Type", TypeName.ToString());
            attributes.Add("Color", PaintColor);
            attributes.Add("LineWidth", LineWidth);
            attributes.Add("Operator", RegOperator.ToString());
            nodes = new Dictionary<string, object>();
            nodes.Add("StartPoint", StartPoint.X.ToString("0.000") + "," + StartPoint.Y.ToString("0.000"));
            nodes.Add("EndPoint", EndPoint.X.ToString("0.000") + "," + EndPoint.Y.ToString("0.000"));
            nodes.Add("Alias", string.IsNullOrEmpty(Alias) ? "" : Alias);
        }
    }
}
